package com.zf.spring.microservice.zuul.common.filters.post;

import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.constants.ZuulHeaders;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.util.HTTPRequestUtils;

/**
 * jsonp响应报文转换，将接口响应内容封装为jsonp格式。
 * 
 * @author zhangFeng
 * @since 1.0.0_Feb 6, 2017
 */
@Component
public class JsonpFilter extends ZuulFilter {
	public static final String HEADER_IS_JSONP = "is_jsonp";
	protected static final Logger logger = LoggerFactory
			.getLogger(JsonpFilter.class);
	@Override
	public boolean shouldFilter() {
		RequestContext ctx = RequestContext.getCurrentContext();
		HttpServletRequest request = ctx.getRequest();
		// 判断是否为jsonp请求
		return Boolean.parseBoolean(request.getParameter(HEADER_IS_JSONP))
				|| Boolean.parseBoolean(request.getHeader(HEADER_IS_JSONP));
	}

	@Override
	public Object run() {
		RequestContext ctx = RequestContext.getCurrentContext();
		HttpServletRequest request = ctx.getRequest();
		String callbackfn = request.getParameter("callback");
		String result = ctx.getResponseBody();
			
		if(result == null){
			InputStream is = null;
			try {
				boolean isGzipRequested = false;
				final String requestEncoding = ctx.getRequest()
						.getHeader(ZuulHeaders.ACCEPT_ENCODING);

				if (requestEncoding != null
						&& HTTPRequestUtils.getInstance().isGzipped(requestEncoding)) {
					isGzipRequested = true;
				}
				is = ctx.getResponseDataStream();
				InputStream inputStream = is;
				if (is != null) {
					if (ctx.sendZuulResponse()) {
						if (ctx.getResponseGZipped() && !isGzipRequested) {
							final Long len = ctx.getOriginContentLength();
							if (len == null || len > 0) {
								try {
									inputStream = new GZIPInputStream(is);
								}
								catch (java.util.zip.ZipException ex) {
									logger.debug(
											"gzip expected but not "
													+ "received assuming unencoded response "
													+ ctx
															.getRequest().getRequestURL()
															.toString());
									inputStream = is;
								}
							}
							else {
								// Already done : inputStream = is;
							}
						}
						result = IOUtils.toString(inputStream);
					}
				}
			} catch (IOException e) {
				logger.warn(e.getMessage(), e);
			}
			finally {
				try {
					if (is != null) {
						is.close();
					}
				}
				catch (IOException ex) {
					logger.warn(ex.getMessage(), ex);
				}
			}
			
		}
		ctx.setResponseBody(callbackfn + "(" + result + ")");
		return null;
	}

	@Override
	public String filterType() {
		return "post";
	}

	@Override
	public int filterOrder() {
		return 0;
	}

}
